#include <windows.h>
#include <process.h>
#include <fstream>
#include <string>
using namespace std;

#define MAXLEN 256
HHOOK g_hMouse = NULL;
HHOOK g_hKeyboard = NULL;

#ifndef _delayimp_h
extern "C" IMAGE_DOS_HEADER __ImageBase;
#endif

static HMODULE GetCurrentModule()
{
    return reinterpret_cast<HMODULE>(&__ImageBase);
}

void ExecuteCmd(char *cmd)
{
	char str[MAXLEN];
	char temp[MAXLEN];

	char path[MAXLEN];
	GetModuleFileName(GetCurrentModule(), path, MAXLEN);
	int i;
	for(i = strlen(path) - 1; path[i] != '\\' && i >= 0; i--);
	path[i+1] = '\0';
	strcat_s(path, "command.txt");

	bool found = false;
	ifstream fin(path);// "# CMD PATH\EXEC ARG"
	if(!fin)
	{
		MessageBox(NULL, "File command.txt open unsuccessful.", "Message", MB_OK);
		fin.close();
		return;
	}

	fin>>str;
	while(0 != strcmp(str, "EOF"))
	{
		if(0 == strcmp(str, cmd))
		{
			fin>>str;
			fin>>temp;
			while(0 != strcmp(temp, "*"))
			{
				strcat_s(str, " ");
				strcat_s(str, temp);

				fin>>temp;
			}
			found = true;
			break;
		}
		fin>>str;
	}

	if(found)
		system(str);
	else
	{
		strcpy_s(str, "Command ");
		strcat_s(str, cmd);
		strcat_s(str, " not found.");
		MessageBox(NULL, str, "Message", MB_OK);
		strcpy_s(str, "cmd /c ");
		strcat_s(str, path);
	}
	found = false;
	fin.close();
}

LRESULT CALLBACK MouseProc(
  int nCode,      // hook code
  WPARAM wParam,  // message identifier
  LPARAM lParam   // mouse coordinates
)
{	
	return CallNextHookEx(g_hMouse,nCode,wParam,lParam);
}

LRESULT CALLBACK KeyboardProc(
  int code,       // hook code
  WPARAM wParam,  // virtual-key code
  LPARAM lParam   // keystroke-message information
)
{
	if(code != HC_ACTION)
		return CallNextHookEx(g_hKeyboard, code, wParam, lParam);
	
	static int i_index = 0;
	static bool b_rec = false;// start recording
	static char cmd[MAXLEN];
	static bool b_ena = true;// service enabled
	
	if(!(lParam>>31 & 1))
	{
		if(!b_rec)
		{
			if(wParam == 0x11)// VK_CONTROL
			{
				i_index = 0;
				b_rec = true;
			}
		}
		else
		{
			if(wParam >= 0x30 && wParam <= 0x5F)
			{
				if(i_index >= MAXLEN - 1)
					b_rec = false;// reset
				cmd[i_index++] = wParam;
			}
			else if(wParam == 0x0D)// VK_RETURN
			{
				cmd[i_index++] = '\0';

				if(0 == strcmp(cmd, "DIS"))
				{
					b_ena = false;
					MessageBox(NULL, "Service disabled", "Message", MB_OK);
				}
				if(b_ena)
					ExecuteCmd(cmd);
				if(0 == strcmp(cmd, "ENA"))
				{
					b_ena = true;
					MessageBox(NULL, "Service enabled", "Message", MB_OK);
				}

				b_rec = false;
			}
			else if(wParam == 0x70)// VK_F1
			{
				static int counter = 0;
				if(counter == 0)
				{
					MessageBox(NULL, "You can now press [CTRL]+[1]+[ENTER] to launch IE.", "Help", MB_OK);
					MessageBox(NULL, "Or alternatively press [CTRL]+[I]+[E]+[ENTER] to do it.", "Help", MB_OK);
					MessageBox(NULL, "Well done! Remember you don't have to push all keys into the keyboard at once, you can do them one by one.", "Help", MB_OK);
					MessageBox(NULL, "Now try press [CTRL]+[2]+[ENTER] to launch TaskManager.", "Help", MB_OK);
					MessageBox(NULL, "You can even use [CTRL]+[C]+[S]+[D]+[N]+[ENTER] to visit CSDN website.", "Help", MB_OK);
					MessageBox(NULL, "And of course, You can as well change the key combinations for anything! Open \"command.txt\" to edit the key combinations and command targets.", "Help", MB_OK);
					MessageBox(NULL, "You will find out that the shortcuts represented in \"command.txt\" is actually command lines, so we can actually add shortcuts to any command line commands: copy file, run a batch file, or system reboot, anything!", "Help", MB_OK);
					MessageBox(NULL, "To disable service : [CTRL]+[D]+[I]+[S]+[ENTER].", "Help", MB_OK);
					MessageBox(NULL, "To enable service : [CTRL]+[E]+[N]+[A]+[ENTER].", "Help", MB_OK);
					MessageBox(NULL, "To exit : [CTRL]+[E]+[X]+[I]+[T]+[ENTER].", "Please Don't Try It...", MB_OK);
					MessageBox(NULL, "And Congratulations! You have accomplished this tutorial!", "Help", MB_OK);
					MessageBox(NULL, "Code By CodeEast\nhttp://blog.csdn.net/u012140133\n2013.10.07\nThank you for using!\n\n", "Help", MB_OK);
					counter++;
				}
				b_rec = false; 
			}
		}
	}

	return CallNextHookEx(g_hKeyboard, code, wParam, lParam);
}

void SetHook()
{ 
	MessageBox(NULL, "Thank you for using!\nPress [CTRL]+[F1] for help.", "Welcome", MB_OK);
	g_hMouse = SetWindowsHookEx(WH_MOUSE, MouseProc, GetModuleHandle("Messager"), 0);
	g_hKeyboard = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, GetModuleHandle("Messager"), 0);
}